package nl.ajonker.railroad.ui.drawcommand;

import nl.ajonker.railroad.pl.RailView;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import static nl.ajonker.railroad.dl.SwitchRail.SwitchState.STRAIGHT;

public class DrawSwitchCommand implements DrawCommand {
    protected static final Color straightColor = Color.GREEN;
    protected static final Color divergingColor = Color.RED;
    protected static final Color textBgColor = Color.DARK_GRAY;

    @Override
    public void draw(Graphics2D g2d, RailView railView, int dimension) {
        AffineTransform saveTransform = g2d.getTransform();

        AffineTransform translate = new AffineTransform();
        translate(translate, railView);
        g2d.transform(translate);

        drawName(g2d, railView, dimension);

        AffineTransform rotate = new AffineTransform();
        rotate(rotate, railView);
        g2d.transform(rotate);

        g2d.setStroke(DrawTrackCommand.stroke);
        g2d.setColor(DrawTrackCommand.railColor);

        if (railView.getSwitchState() == STRAIGHT) {
            g2d.setColor(DrawTrackCommand.railColor);
            drawDiverging(g2d, dimension, railView.getType());

            g2d.setColor(straightColor);
            drawStraight(g2d, dimension);
        } else {
            g2d.setColor(DrawTrackCommand.railColor);
            drawStraight(g2d, dimension);

            g2d.setColor(divergingColor);
            drawDiverging(g2d, dimension, railView.getType());
        }

        g2d.setTransform(saveTransform);
    }

    private static void drawStraight(Graphics2D g2d, int dimension) {
        g2d.drawLine(0, 0, dimension, 0);
    }

    protected static void drawName(Graphics2D g2d, RailView railView, int dimension) {
        RenderingHints orig = g2d.getRenderingHints();
        AffineTransform atOrig = g2d.getTransform();
        g2d.setRenderingHint(
                RenderingHints.KEY_TEXT_ANTIALIASING,
                RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);

        int rotation = railView.getRotation();
        if (rotation == 0)
            g2d.translate(10, 4);
        else if (rotation == 180)
            g2d.translate(-10, 4);

        Font origFont = g2d.getFont();
        g2d.setFont(new Font("Verdana", Font.BOLD, 20));

        FontMetrics fm = g2d.getFontMetrics();
        Rectangle2D rect = fm.getStringBounds(railView.getName(), g2d);

        int x = 0;
        int y = -dimension / 3;
        if (railView.getSwitchState() == STRAIGHT)
            g2d.setColor(straightColor);
        else
            g2d.setColor(divergingColor);

        g2d.fillRect(x, y - fm.getAscent(), (int) rect.getWidth(),
                (int) rect.getHeight());


        g2d.setColor(textBgColor);
        g2d.drawString(railView.getName(), x, y);

        g2d.setRenderingHints(orig);
        g2d.setTransform(atOrig);
        g2d.setFont(origFont);
    }

    private static void drawDiverging(Graphics2D g2d, int dimension, RailView.SwitchType type) {
        AffineTransform original = g2d.getTransform();

        if (type == RailView.SwitchType.LEFT)
            // flip
            g2d.scale(1.0, -1.0);
        g2d.drawArc(-dimension * 2, 0, dimension * 4, dimension * 4, 90, -30);

        g2d.setTransform(original);
    }

    @Override
    public Shape getRegion(RailView railView, int dimension) {
        Rectangle rectangle = new Rectangle(0, 0, dimension, dimension);
        AffineTransform at = new AffineTransform();
        at = translate(at, railView);
        at = rotate(at, railView);
        if (railView.getType() == RailView.SwitchType.LEFT)
            at.scale(1.0, -1.0);

        return at.createTransformedShape(rectangle);
    }

    protected static AffineTransform translate(AffineTransform at, RailView railView) {
        Point position = railView.getPosition();
        at.translate(position.x, position.y);
        return at;
    }

    protected static AffineTransform rotate(AffineTransform at, RailView railView) {
        at.rotate(Math.toRadians(railView.getRotation()));
        return at;
    }
}
